Exploration des sommations discrètes
Technologie jupyter (cliquez pour ouvrir)

La technologie jupyter permet d'exécuter du code python par un simple clique sur Executer ci-dessus.
Les morceaux de code de cette page sont interprétées case par case. Pour savoir quelle case a été interprétée avant une autre, il suffit de repérer le numéro devant la case.
Une fois qu'une case a été interprétée (=exécutée), la page garde en mémoire les variables et fonctions lues
La plateforme propose quelques outils de purge de la mémoire :

  • Il est possible de tout recommencer (dénuméroter) en choisissant dans le menu Kernel ci-dessus Restart & Clear Output pour purger la mémoire de toutes ses variables et de toutes ses executions
  • Dans le menu Kernel choisir Restard & Run All aura le même effet que Restart & Clear Output mais en plus relancera chacune des cases depuis le haut du document jusqu'en bas (renuméroter).

SAUVEGARDER VOTRE TRAVAIL

Pour ne pas perdre votre travail pensez à le sauvegarder régulièrement. Par défault, la sauvegarde par un clic sur la disquette en haut à gauche de page, ou par le racourci clavier classique ctrl+S est une sauvegarde en local, sur le serveur de jupyter. Vous pouvez et devez très régulièrement sauvegarder votre travail sur votre support personnel de sauvegarde (clef USB, se l'envoyer par mail etc). Ce faisant vous disposerez d'un fichier .ipynb (IPYthon NoteBook) qu'il vous suffira de recharger pour avancer. Après le rechargement assurez vous que les fonctionnalités anciennement developpées et variables utilisées sont bien dans la mémoire de la page (en rééxecutant les cases, ou plus rapidement par Kernel > Restart & Run All.

A NOTER : vous pouvez travailler sur le tp (et tout autre fichier .ipynb) hors connexion en installant une version local du notebook de jupyter. Il faut que votre machine possède un interpreteur de python et que vous soyez connecter à internet.

  1. Lancer un terminal
  2. Taper la commande suivante : pip install jupyterlab
  3. Une fois l'installation terminée portez votre attention sur les dernières lignes affichées dans votre terminal vous invitant probablement à taper une ligne de commande pour faire une mise à jour
  4. Pour lancer notebook de jupyter, taper dans votre termial : jupyter notebook
  5. Votre simulateur de serveur est lancé. Il ne faut pas fermer votre terminal, auquel cas votre simulateur de serveur s'interompera. Suivez le lien indiqué dans les dernières lignes de votre terminal pour vous diriger vers votre espace local. L'interface se présente comme celle que vous trouverez sur le web. Votre travail sera cependant toujours enregistré et jamais perdu même si vous le consultez après plusieurs jours

Il ne s'agit pas ici de faire un cours de python mais simplement de rappeler les éléments majeurs que nous allons utiliser pour programmer. Si vous êtes familier avec le langage vous pouvez aller directement à la première partie.

Les tableaux (cliquez pour ouvrir) Il existe plusieurs moyens de faire des tableaux en python. Nous revennons sur les deux dont nous abuserons tout au long de ce TP :
  1. Les listes
    Il est nécessaire de déclarer les listes. Pour ce faire, il suffit d'écrire
    L=[]
    Pour ajouter un élément à une liste, il faut utiliser append qui va ajouter la valeur passée en paramètre à la fin du tableau.
    L=[]
    L.append(4)
  2. Les dictionnaires
    Il est nécessaire de déclarer les dictionnaires. Pour ce faire, il suffit d'écrire
    L=dict()
    Pour ajouter un élément à une liste, il suffit de préciser la valeur à donner à la case souhaitée.
    L=dict()
    L[0]=4
Si vous n'êtes pas très familier avec les tableaux, le choix des dictionnaires est un bon compromis.
Quelque soit le choix de structure que vous faites, la fonction len vous donnera la taille du tableau.
L=[]
print(len(L))#Affichera 0
L.append(4)
L.append(-1)
print(len(L))#Affichera 2
Enfin, gardez en mémoire qu'une tableau est en fait une adresse de ce fait, passer des tableaux en paramètre de fonction ne crée pas de copie des tableaux mais modifie bien le tableau originel. Il vous appartient de maitriser et de ne pas écraser les données du tableau en créant une copie.
Les boucles (cliquez pour ouvrir) Il existe en python deux outils permettant de faire des boucles.
  1. while
    C'est la boucle la plus confortable mais qui peut générer des itérations infinies si le test n'est pas bien pensé ou l'itérateur mal incrémenté
    while(test) :
  2. for
    Une fois cette boucle lancée, nul besoin de controler l'itérateur ou de gérer le test. Lorsque l'on veut parcourir les entiers entre $a$ et $b$ d'un pas de $p$ on l'utilise avec range(a, b, p) qui génére un tableau (liste) de nombre entre $a$ et $b-1$ de $p$ en $p$
    for i in range(-4, 8, 3) :
    Dans cette exemple, la variable $i$ (l'itérateur), vaudra succésivement $-4$, $-1$, $2$ et $5$ (le $8$ n'est pas atteint car range(a, b, p) créé une liste d'entier entre $a$ et $b-1$).
    La boucle for permet de se servir de n'importe quel tableau comme ensemble d'indice. Attention cependant, dictionnaire et liste n'engendre pas le même ensemble.
    L=[1, 2, 4]
    for i in L :
    Dans cet exemple $L[0]=1$, $L[1]=2$ et $L[2]=4$ tandis que l'itérateur $i$ vaut succéssivement $1$, $2$ et $4$ c'est à dire les valeurs de la liste
    L={0:1, 1: 2, 2:4}
    for i in L :
    Dans cet exemple nous avons aussi $L[0]=1$, $L[1]=2$ et $L[2]=4$ bien que $L$ soit un dictionnaire et non une liste comme précédement. Cependant l'itérateur $i$ vaut succéssivement $0$, $1$ et $2$ c'est à dire les clefs des valeurs du dictionnaire

Considérons la liste suivante

In [1]:
L=list(range(0, 20, 3))
print(L)
[0, 3, 6, 9, 12, 15, 18]

Nous souhaitons faire la somme des carrés des termes de cette suite. Voici deux solutions : une avec la boucle while et l'autre avec la boucle for.

In [2]:
#Avec une boucle while (6 lignes)
res1=0
i=0
while(i<len(L)) : 
    res1+=L[i]**2
    i+=1
print("res1 =", res1)

#Avec une boucle for (3 lignes)
res2=0
for x in L : res2+=x**2
print("res2 =", res2)
res1 = 819
res2 = 819

Exercice 1

Donner la liste des 100 premier terme de la suite $u_n=\dfrac{(-1)^n+1}{2}$.

In [3]:
Un=[]
for n in range(0, 100, 1) : 
    Un.append(((-1)**n+1)/2)
print(Un)
[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]

Suivant la parité de $n$, on observe que $u_n$ prend des valeurs bien particulière. Ecrire une fonction f qui prend un paramètre n et renvoie $u_n$ sans calculer $\dfrac{(-1)^n+1}{2}$. Exécuter la case suivante permettant de vérifier votre formule.

In [4]:
def f(n) :
    if(n%2==0) : return 1.0
    return 0.0
In [5]:
N=[0, 10, 25, 50, 75]
for n in N : 
    print("Pour n =", n, "\n\tFormule1 =", Un[n], "\n\tFormule2 =", f(n))
    if(Un[n]==f(n)) : print("\tTout va bien")
    else : print("\tPROBLEME !!!")
Pour n = 0 
	Formule1 = 1.0 
	Formule2 = 1.0
	Tout va bien
Pour n = 10 
	Formule1 = 1.0 
	Formule2 = 1.0
	Tout va bien
Pour n = 25 
	Formule1 = 0.0 
	Formule2 = 0.0
	Tout va bien
Pour n = 50 
	Formule1 = 1.0 
	Formule2 = 1.0
	Tout va bien
Pour n = 75 
	Formule1 = 0.0 
	Formule2 = 0.0
	Tout va bien

Nous allons comparer les temps de calculs. Pour cela nous avons besoin de la fonction time de la bibliothèque éponyme.

In [6]:
from time import time

Pour déterminer le nombre de seconde écouler depuis le 1er janvier 1970, on appel la fonction time sans paramètre.

In [7]:
x=time()
print(x)
1678896215.7673306

Ainsi pour déterminer le temps d'exécution d'un programe, on fait un top avant l'algorithme et un top à la fin. La différence de ces deux top donnera donc le nombre de seconde écouler le temps de l'éxécution du programme.

In [8]:
top=time()
for i in range(10**6) : 
    i=i**2
print("Temps :", time()-top)
Temps : 0.30036449432373047

Le code suivant donne le temps de calcul de $u_{n}$ pour $n=10^{10^6}$ (dix puissance un million)

In [9]:
n=10**(10**6) #On place le calcul de n avant le comptage du temps de calcul
top=time()
x=((-1)**(n)+1)/2
print("Temps de calcul de u_n :", time()-top)
Temps de calcul de u_n : 0.03591465950012207

Faisons le même calcul en passant par la fonction f déterminée précédement.

In [10]:
n=10**(10**6)
top=time()
x=f(n)
print("Temps de calcul de u_n :", time()-top)
Temps de calcul de u_n : 0.0019953250885009766

Ainsi avoir remarqué que $u_n=f(n)$ pour une fonction $f$ pas trop compliqué simplifie considérablement les temps de calcul.

Calculer $\displaystyle{\sum_{n=0}^{99}u_n}$.

In [11]:
res=0
for un in Un : 
    res+=un
print("Résultat :", res)
Résultat : 50.0

Calculer $\displaystyle{\sum_{n=0}^{999999}u_n}$.

In [12]:
#Il parait plus raisonnable, aux vues des temps de calcul, de passer par la fonction f
res=0
for n in range(10**6) : res+=f(n)
print("Résultat :", res)
Résultat : 500000.0

Exercice 2

On peut montrer par récurrence que $\displaystyle{\sum_{k=0}^n k=\dfrac{n(n+1)}{2}}$. Calculer la somme pour $n=10$, $n=1000$ et $n=1983$ et vérifier qu'elle est bien égale à l'expression $\dfrac{n(n+1)}{2}$

In [13]:
N=[10, 1000, 1983]
for n in N : 
    s=0
    for k in range(0, n+1, 1) : s+=k
    x=(n*(n+1))/2
    print("Sommation :", s)
    print("Formule :", x)
    if(s==x) : print("\tTout va bien")
    else : print("\tPROBLEME !!")
Sommation : 55
Formule : 55.0
	Tout va bien
Sommation : 500500
Formule : 500500.0
	Tout va bien
Sommation : 1967136
Formule : 1967136.0
	Tout va bien

Exercice 3

On peut montrer par récurrence que $\displaystyle{\sum_{k=0}^n k^2=\dfrac{n(n+1)(2n-1)}{6}}$. Calculer la somme pour $n=10$, $n=1000$ et $n=1983$ et vérifier qu'elle est bien égale à l'expression $\dfrac{n(n+1)(2n+1)}{6}$

In [14]:
N=[10, 1000, 1983]
for n in N : 
    s=0
    for k in range(0, n+1, 1) : s+=k**2
    x=(n*(n+1)*(2*n+1))/6
    print("Sommation :", s)
    print("Formule :", x)
    if(s==x) : print("\tTout va bien")
    else : print("\tPROBLEME !!")
Sommation : 385
Formule : 385.0
	Tout va bien
Sommation : 333833500
Formule : 333833500.0
	Tout va bien
Sommation : 2601209504
Formule : 2601209504.0
	Tout va bien

Exercice 4

On peut montrer par récurrence que $\displaystyle{\sum_{k=0}^n 2^k=2^{n+1}-1}$. Calculer la somme pour $n=10$, $n=1000$ et $n=1983$ et vérifier qu'elle est bien égale à l'expression $2^{n+1}-1$

In [15]:
N=[10, 1000, 1983]
for n in N : 
    s=0
    for k in range(0, n+1, 1) : s+=2**k
    x=2**(n+1)-1
    print("Sommation :", s)
    print("Formule :", x)
    if(s==x) : print("\tTout va bien")
    else : print("\tPROBLEME !!")
Sommation : 2047
Formule : 2047
	Tout va bien
Sommation : 21430172143725346418968500981200036211228096234110672148875007767407021022498722449863967576313917162551893458351062936503742905713846280871969155149397149607869135549648461970842149210124742283755908364306092949967163882534797535118331087892154125829142392955373084335320859663305248773674411336138751
Formule : 21430172143725346418968500981200036211228096234110672148875007767407021022498722449863967576313917162551893458351062936503742905713846280871969155149397149607869135549648461970842149210124742283755908364306092949967163882534797535118331087892154125829142392955373084335320859663305248773674411336138751
	Tout va bien
Sommation : 1751908409537131537220509645351687597690304110853111572994449976845956819751541616602568796259317428464425605223064365804210081422215355425149431390635151955247955156636234741221447435733643262808668929902091770092492911737768377135426590363166295684370498604708288556044687341394398676292971255828404734517580702346564613427770683056761383955397564338690628093211465848244049196353703022640400205739093118270803778352768276670202698397214556629204420309965547056893233608758387329699097930255380715679250799950923553703740673620901978370802540218870279314810722790539899334271514365444369275682815
Formule : 1751908409537131537220509645351687597690304110853111572994449976845956819751541616602568796259317428464425605223064365804210081422215355425149431390635151955247955156636234741221447435733643262808668929902091770092492911737768377135426590363166295684370498604708288556044687341394398676292971255828404734517580702346564613427770683056761383955397564338690628093211465848244049196353703022640400205739093118270803778352768276670202698397214556629204420309965547056893233608758387329699097930255380715679250799950923553703740673620901978370802540218870279314810722790539899334271514365444369275682815
	Tout va bien

Exercice 5

On peut montrer que pour tout $x\in\mathbb{R}_+$, il existe un entier $N\in \mathbb{N}$ tel que $\displaystyle{\sum_{n=1}^{N}\dfrac{1}{n}>x}$. Déterminer le plus petit $N$ pour $x=5$, $x=10$, $x=15$ et $x=20$. Mesurer les temps de calcul.

In [16]:
X=[5, 10, 15, 20]
for x in X :
    top=time()
    s=0
    n=1
    while(s<=x) : 
        s+=1/n
        n+=1
    n-=1
    print("Pour N =", n, "on atteint", x)
    print("\tTemps de calcul :", time()-top)
Pour N = 83 on atteint 5
	Temps de calcul : 0.0009930133819580078
Pour N = 12367 on atteint 10
	Temps de calcul : 0.0019989013671875
Pour N = 1835421 on atteint 15
	Temps de calcul : 0.8147811889648438
Pour N = 272400600 on atteint 20
	Temps de calcul : 79.88578271865845
In [ ]: